//-------------------------------------------------------------------
//	Copyright (c) 2013-2014  Zhirnov Andrey
//	This file is part of the "UX OpwnGL Framework" project.
//	See copyright notice in "UX_GL_Framework.h".
//-------------------------------------------------------------------

#pragma once

#include <Common.h>

class CSampleApplication : public CApplication
{
// types
private:
	struct TerrainUB
	{
		fvec3	vLightDir;
		float	fGridScale;

		float	fMaxTessLevel;
		float	fHeightScale;
		float	fDetailLevel;
		float	__align[1];
		///
		TerrainUB () :
			vLightDir(),
			fGridScale(100.0f), fMaxTessLevel(12.0f),
			fHeightScale(-5.0f), fDetailLevel(100.0f)
		{
			//vLightDir = fvec3(0.3f, 0.6f, 0.3f).Normalized();
			vLightDir = fvec3(0.0f, 0.0f, 1.0f).Normalized();
		}

		static float	HeightScaleStep ()		{ return 0.5f; }
		static float	DetailLevelStep ()		{ return 1.0f; }
		static float	TessLevelStep ()		{ return 1.0f; }
		static float	GridScaleStep ()		{ return 1.0f; }
	};
	STATIC_ASSERTE( sizeof(TerrainUB) % sizeof(fvec4) == 0 );


	typedef GLUniformBlock< TerrainUB >		terrainUB_t;
	typedef GLUniform< fmat4 >				uniformMat4_t;
	typedef GLUniform< int >				sampler2D_t;

	struct EViewMode
	{
		enum type
		{
			TERRAIN_3D = 0,
			TERRAIN_3D_NORMALS,
			TERRAIN_3D_TESSLVL,
			HEIGHT_MAP,
			NORMAL_MAP,
		};
	};

	struct TerrainData
	{
		GLProgramPtr	prog;
		sampler2D_t		unHeightMap,
						unNormalMap,
						unDiffuseMap;
		terrainUB_t		ub;
		uniformMat4_t	matMVP;
		uint			patchSize;
		///
		TerrainData () : patchSize(0) {}
	};

	struct TerrainNormalsData
	{
		GLProgramPtr	prog;
		sampler2D_t		unHeightMap,
						unNormalMap;
		terrainUB_t		ub;
		uniformMat4_t	matMVP;
		uint			patchSize;
		///
		TerrainNormalsData () : patchSize(0) {}
	};

	struct TerrainTesslvlData
	{
		GLProgramPtr	prog;
		sampler2D_t		unHeightMap,
						unNormalMap;
		terrainUB_t		ub;
		uniformMat4_t	matMVP;
		uint			patchSize;
		///
		TerrainTesslvlData () : patchSize(0) {}
	};


// variables
private:
	TerrainData			terrainData;
	TerrainNormalsData	terrainNormalsData;
	TerrainTesslvlData	terrainTesslvlData;

	GLProgramPtr		progViewHeight,
						progViewNormals;

	GLTexture2DPtr		texHeight,
						texNormals;
	GLTexture2DArrayPtr	texTiles;

	GLRenderState		rsTerrain,
						rsView;
	
	GLMeshPtr			grid;

	camera_f			camera;

	EViewMode::type		viewMode;

	bool				cursorIsHidden : 1;
	bool				vsyncEnabled : 1;
	bool				wireframe : 1;


// methods
public:
	CSampleApplication ();
	~CSampleApplication ();

	void Draw () override;
	void Update () override;
	void OnResize () override;
	void OnInit () override;
	void OnFree () override;
	
	static bool Run ();

private:
	void _GenNormals ();

	void _GenTexArray ();
};
